<script setup lang="ts">
import type { FormInstance } from 'element-plus'
import type { LocationQuery, LocationQueryValue } from 'vue-router'
import { useRoute } from 'vue-router'
import { useSettingsStore, useUserStore } from '@/store'
import AuthAPI from '@/api/auth'
import type { LoginData } from '@/api/auth/model'
import router from '@/router'
import defaultSettings from '@/settings'
import { ThemeEnum } from '@/enums/ThemeEnum'

// Stores
const userStore = useUserStore()
const settingsStore = useSettingsStore()

// Reactive states
const isDark = ref(settingsStore.theme === ThemeEnum.DARK)
const loading = ref(false) // 按钮loading
const isCapslock = ref(false) // 是否大写锁定
const captchaBase64 = ref() // 验证码图片Base64字符串
const loginFormRef = ref<FormInstance>() // 登录表单ref

const loginData = ref<LoginData>({
  username: 'admin',
  password: '123456',
})

const loginRules = computed(() => {
  return {
    username: [
      {
        required: true,
        trigger: 'blur',
        message: 'login.message.username.required',
      },
    ],
    password: [
      {
        required: true,
        trigger: 'blur',
        message: 'login.message.password.required',
      },
      {
        min: 6,
        message: 'login.message.password.min',
        trigger: 'blur',
      },
    ],
    captchaCode: [
      {
        required: true,
        trigger: 'blur',
        message: 'login.message.captchaCode.required',
      },
    ],
  }
})

/** 获取验证码 */
function getCaptcha() {
  AuthAPI.getCaptcha().then((data) => {
    loginData.value.captchaKey = data.captchaKey
    captchaBase64.value = data.captchaBase64
  })
}

/** 登录 */
const route = useRoute()
function handleLogin() {
  loginFormRef.value?.validate((valid: boolean) => {
    if (valid) {
      loading.value = true
      userStore
        .login(loginData.value)
        .then(() => {
          const query: LocationQuery = route.query
          const redirect = (query.redirect as LocationQueryValue) ?? '/'
          const otherQueryParams = Object.keys(query).reduce(
            (acc: any, cur: string) => {
              if (cur !== 'redirect')
                acc[cur] = query[cur]

              return acc
            },
            {},
          )

          router.push({ path: redirect, query: otherQueryParams })
        })
        .catch(() => {
          getCaptcha()
        })
        .finally(() => {
          loading.value = false
        })
    }
  })
}

/** 主题切换 */
function toggleTheme() {
  const newTheme
    = settingsStore.theme === ThemeEnum.DARK ? ThemeEnum.LIGHT : ThemeEnum.DARK
  settingsStore.changeTheme(newTheme)
}

/** 检查输入大小写 */
function checkCapslock(event: KeyboardEvent) {
  // 防止浏览器密码自动填充时报错
  if (event instanceof KeyboardEvent)
    isCapslock.value = event.getModifierState('CapsLock')
}

onMounted(() => {
  getCaptcha()
})
</script>

<template>
  <div class="login-container">
    <!-- 顶部 -->
    <div class="absolute-lt flex-x-end p-3 w-full">
      <el-switch v-model="isDark" inline-prompt active-icon="Moon" inactive-icon="Sunny" @change="toggleTheme" />
    </div>
    <!-- 登录表单 -->
    <el-card class="!border-none !bg-transparent !rounded-4% w-100 <sm:w-85">
      <div class="text-center relative">
        <h2>{{ defaultSettings.title }}</h2>
        <el-tag class="ml-2 absolute-rt">
          {{ defaultSettings.version }}
        </el-tag>
      </div>

      <el-form ref="loginFormRef" :model="loginData" :rules="loginRules" class="login-form">
        <!-- 用户名 -->
        <el-form-item prop="username">
          <div class="flex-y-center w-full">
            <svg-icon icon-class="user" class="mx-2" />
            <el-input
              ref="username" v-model="loginData.username" placeholder="login.username" name="username"
              size="large" class="h-[48px]"
            />
          </div>
        </el-form-item>

        <!-- 密码 -->
        <el-tooltip :visible="isCapslock" content="login.capsLock" placement="right">
          <el-form-item prop="password">
            <div class="flex-y-center w-full">
              <svg-icon icon-class="lock" class="mx-2" />
              <el-input
                v-model="loginData.password" placeholder="login.password" type="password" name="password"
                size="large" class="h-[48px] pr-2" show-password @keyup="checkCapslock" @keyup.enter="handleLogin"
              />
            </div>
          </el-form-item>
        </el-tooltip>

        <!-- 验证码 -->
        <el-form-item prop="captchaCode">
          <div class="flex-y-center w-full">
            <svg-icon icon-class="captcha" class="mx-2" />
            <el-input
              v-model="loginData.captchaCode" auto-complete="off" size="large" class="flex-1"
              placeholder="login.captchaCode" @keyup.enter="handleLogin"
            />

            <el-image
              :src="captchaBase64" class="rounded-tr-md rounded-br-md cursor-pointer h-[48px]"
              @click="getCaptcha"
            />
          </div>
        </el-form-item>

        <!-- 登录按钮 -->
        <el-button :loading="loading" type="primary" size="large" class="w-full" @click.prevent="handleLogin">
          {{
            'login.login' }}
        </el-button>

        <!-- 账号密码提示 -->
        <div class="mt-10 text-sm">
          <span>{{ 'login.username' }}: admin</span>
          <span class="ml-4"> {{ 'login.password' }}: 123456</span>
        </div>
      </el-form>
    </el-card>
  </div>
</template>

<style lang="scss" scoped>
html.dark .login-container {
  background: url("@/assets/images/login-bg-dark.jpg") no-repeat center right;
}

.login-container {
  overflow-y: auto;
  background: url("@/assets/images/login-bg.jpg") no-repeat center right;

  @apply wh-full flex-center;

  .login-form {
    padding: 30px 10px;
  }
}

.el-form-item {
  background: var(--el-input-bg-color);
  border: 1px solid var(--el-border-color);
  border-radius: 5px;
}

:deep(.el-input) {
  .el-input__wrapper {
    padding: 0;
    background-color: transparent;
    box-shadow: none;

    &.is-focus,
    &:hover {
      box-shadow: none !important;
    }

    input:-webkit-autofill {
      /* 通过延时渲染背景色变相去除背景颜色 */
      transition: background-color 1000s ease-in-out 0s;
    }
  }
}
</style>
